package cn.tedu.charging.order.service.impl;

import cn.tedu.charging.common.constant.AmqpComponentConst;
import cn.tedu.charging.common.constant.MqttDestinationConst;
import cn.tedu.charging.common.pojo.message.ChargingStartCheckMessage;
import cn.tedu.charging.common.pojo.message.DelayCheckMessage;
import cn.tedu.charging.common.pojo.param.OrderAddParam;
import cn.tedu.charging.common.pojo.vo.VehicleVO;
import cn.tedu.charging.common.protocol.JsonResult;
import cn.tedu.charging.common.utils.CronUtil;
import cn.tedu.charging.common.utils.SnowflakeIdGenerator;
import cn.tedu.charging.order.emqx.MqttProducer;
import cn.tedu.charging.order.feign.DeviceClient;
import cn.tedu.charging.order.feign.UserClient;
import cn.tedu.charging.order.rabbitmq.AmqpProducer;
import cn.tedu.charging.order.service.OrderService;
import cn.tedu.charging.order.utils.XxlJobTaskUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderServiceImpl implements OrderService {

    private final DeviceClient deviceClient;
    private final UserClient userClient;
    private final SnowflakeIdGenerator snowflakeIdGenerator;
    private final MqttProducer<ChargingStartCheckMessage> mqttProducer;
    private final AmqpProducer<DelayCheckMessage> amqpProducer;

    @Autowired
    public OrderServiceImpl(DeviceClient deviceClient, UserClient userClient, SnowflakeIdGenerator snowflakeIdGenerator,
    MqttProducer<ChargingStartCheckMessage> mqttProducer, AmqpProducer<DelayCheckMessage> amqpProducer) {
        this.deviceClient = deviceClient;
        this.userClient = userClient;
        this.snowflakeIdGenerator = snowflakeIdGenerator;
        this.mqttProducer = mqttProducer;
        this.amqpProducer = amqpProducer;
    }

    public String createOrder(OrderAddParam param) {
        // 1.根据入参参数 检查枪状态
        Integer gunId = param.getGunId();
        JsonResult<Boolean> result = deviceClient.checkGun(gunId);
        if (!result.getData()){
            throw new RuntimeException("枪不可用");
        }
        // 2.检查车主
        JsonResult<VehicleVO> vo = userClient.bindedVehicle(param.getUserId());
        if (vo.getData() == null){
            throw new RuntimeException("车主未绑定车辆");
        }
        // 3.生成本次扫码下单的订单编号（雪花算法）
        Long billNo = snowflakeIdGenerator.nextId();
        String orderNo = String.valueOf(billNo);
        // 4.发送生产消息给设备开始自检
        ChargingStartCheckMessage message = new ChargingStartCheckMessage();
        message.setGunId(gunId);
        message.setOrderNo(orderNo);
        message.setUserId(param.getUserId());
        mqttProducer.sendAtLeastOnceStored(MqttDestinationConst.START_GUN_CHECK_PREFIX + param.getPileId(),message);

        // 5.订单给设备发送检测命令，准备延迟逻辑 检查最终设备自检结果
        DelayCheckMessage delayCheckMessage = new DelayCheckMessage();
        delayCheckMessage.setOrderNo(orderNo);
        delayCheckMessage.setUserId(param.getUserId());
        delayCheckMessage.setGunId(gunId);
        delayCheckMessage.setPileId(param.getPileId());
        delayCheckMessage.setVehicleId(vo.getData().getId());
        amqpProducer.send(delayCheckMessage, AmqpComponentConst.DELAY_BILL_EX);

        // 6.组织一个定时任务，防止订单长时间未充完，无法结束
        String expression = CronUtil.delayCron(1000*60*30); // 生成cron表达式 时间是30分钟(便于测试时间可以再短)
        XxlJobTaskUtil.createJobTask(new RestTemplate(),expression,4,orderNo);// 发起一个http请求 创建定时任务

        return orderNo;
    }
}
